package com.zmc.order.application.impl;

import com.zmc.common.annotation.PreventRepeatSubmit;
import com.zmc.common.domain.freight.FreightQueryPrice;
import com.zmc.common.domain.freight.FreightSendAddress;
import com.zmc.common.domain.good.GoodSkuBuyDetail;
import com.zmc.common.domain.resp.freight.FreightPriceResp;
import com.zmc.common.domain.resp.order.ThirdPayResp;
import com.zmc.common.domain.vo.member.MemberAddressInfo;
import com.zmc.common.domain.vo.order.OrderPayInfo;
import com.zmc.common.enums.RequestSourceEnum;
import com.zmc.common.exception.base.BusinessException;
import com.zmc.common.utils.*;
import com.zmc.order.feign.*;
import com.zmc.order.infrastructure.bean.query.OrderManageQuery;
import com.zmc.order.infrastructure.bean.resp.OrderInfoResp;
import com.zmc.order.application.OrderApplicationService;
import com.zmc.order.infrastructure.bean.resp.OrderPayResp;
import com.zmc.order.infrastructure.bean.vo.OrderReturnApplyVo;
import com.zmc.order.infrastructure.entity.OrderEntity;
import com.zmc.order.infrastructure.entity.OrderItemEntity;
import com.zmc.order.infrastructure.updater.order.OrderFactory;
import com.zmc.order.infrastructure.service.*;
import com.zmc.order.infrastructure.bean.vo.SubmitOrderVo;
import com.zmc.order.infrastructure.enums.OrderEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：zmc
 * @Date：2024/11/7 10:01
 */

@Component
public class OrderApplicationServiceImpl implements OrderApplicationService {

    public static Logger log = LoggerFactory.getLogger(OrderApplicationServiceImpl.class);


    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private MemberFeignService memberFeignService;

    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private ThirdFeignService thirdFeignService;

    @Autowired
    private AdminFeignService adminFeignService;

    @Autowired
    private OrderFactory<Object> orderFactory;

    public static String upLoadPrefix = "http://localhost:8080/api";

    @Value("${order.expire-time}")
    private Long expireTime;


    @Override
    @PreventRepeatSubmit(lockByPerson = true, source = RequestSourceEnum.WEB)
    public void submit(SubmitOrderVo vo) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_CREATE.getCode()).execute(vo);
    }

    @Override
    public OrderPayResp getOrderPayInfo(String orderSn) {
        OrderEntity order = null;
        if (StringUtils.isEmpty(orderSn)) {
            order = orderService.getLastWaitPayOrder();
        } else {
            order = orderService.getByOrderSn(orderSn);
        }
        if (order == null) {
            log.error("查询待支付订单,不存在");
            throw new BusinessException("没有待支付订单");
        }
        OrderPayResp resp = new OrderPayResp();
        resp.setFormatTime(order.getCreateTime());
        resp.setOrderNo(order.getOrderSn());
        resp.setPayMoney(order.getPayAmount());
        resp.setCountdown(DateUtils.towTimeDivide(order.getCreateTime(), LocalDateTime.now(), expireTime));
        return resp;
    }

    @Override
    public OrderPayInfo getThirdPayInfo(String orderSn) {
        OrderEntity order = orderService.getByOrderSn(orderSn);
        List<OrderItemEntity> list = orderItemService.listByOrderSn(orderSn);
        String collect = list.stream().map(OrderItemEntity::getSpuName).collect(Collectors.joining(","));
        OrderPayInfo info = new OrderPayInfo();
        info.setOrderNo(orderSn);
        info.setTotalAmount(order.getPayAmount());
        info.setSubject(collect);
        return info;
    }

    @Override
    public PageUtils pageOrder(OrderManageQuery query) {
        return orderService.pageList(query);
    }

    @Override
    @PreventRepeatSubmit(key = "#orderSn", openSpEL = true)
    public void cancelOrder(String orderSn) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_CANCEL.getCode()).execute(orderSn);
    }

    @Override
    public OrderInfoResp orderInfo(String orderSn) {
        OrderInfoResp resp = new OrderInfoResp();
        OrderEntity order = orderService.getByOrderSn(orderSn);
        List<OrderItemEntity> items = orderItemService.listByOrderSn(orderSn);
        items.forEach(item -> {
            item.setSkuPic(upLoadPrefix + item.getSkuPic());
        });
        order.setItems(items);
        resp.setOrder(order);
        R r = memberFeignService.receiveAddressInfo(order.getReceiverAddressId());
        MemberAddressInfo addressInfo = JsonUtils.transToClass(r, MemberAddressInfo.class);
        resp.setAddressInfo(addressInfo);
        return resp;
    }

    @Override
    @PreventRepeatSubmit(key = "#payResp.orderNo", openSpEL = true)
    public void splitOrder(ThirdPayResp payResp) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_SPLIT.getCode()).execute(payResp);
    }

    @Override
    @PreventRepeatSubmit(key = "#vo.orderSn", openSpEL = true)
    public void applyRefund(OrderReturnApplyVo vo) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_APPLY_REFUND.getCode()).execute(vo);
    }

    @Override
    @PreventRepeatSubmit(key = "#vo.orderSn", openSpEL = true)
    public void approveRefund(OrderReturnApplyVo vo) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_APPROVE_REFUND.getCode()).execute(vo);
    }

    @Override
    @PreventRepeatSubmit(key = "#orderSn", openSpEL = true)
    public void refundHandle(String orderSn) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_REFUND_HANDLER.getCode()).execute(orderSn);
    }

    @Override
    public R paySuccessDetail(String orderSn) {
        OrderEntity order = orderService.getByOrderSn(orderSn);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        Long receiverAddressId = order.getReceiverAddressId();
        return memberFeignService.receiveAddressInfo(receiverAddressId);
    }

    @Override
    @PreventRepeatSubmit(key = "#orderSn", openSpEL = true)
    public void orderCreateLogistics(String orderSn) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_CREATE_LOGISTICS.getCode()).execute(orderSn);
    }

    @Override
    public FreightPriceResp queryFreightPrice(String orderSn) {
        OrderEntity order = orderService.getByOrderSn(orderSn);
        if (order == null) {
            throw new BusinessException("订单不存在");
        }
        List<OrderItemEntity> list = orderItemService.listByOrderSn(orderSn);
        List<GoodSkuBuyDetail> collect = new ArrayList<>();
        list.stream().collect(Collectors.groupingBy(OrderItemEntity::getSpuId)).forEach((spuId, items) -> {
            GoodSkuBuyDetail detail = new GoodSkuBuyDetail();
            int sum = (int)items.stream().mapToLong(OrderItemEntity::getSkuQuantity).sum();
            detail.setSpuId(spuId);
            detail.setSkuQuantity(sum);
            collect.add(detail);
        });
        //价格查询
        FreightQueryPrice queryPrice = JsonUtils.transToClass(productFeignService.countWeightVolume(collect), FreightQueryPrice.class);
        FreightSendAddress freightSendAddress = JsonUtils.transToClass(adminFeignService.getUserIdentity(order.getMerchantId()), FreightSendAddress.class);
        queryPrice.setSrcPostCode(freightSendAddress.getPostCode());
        MemberAddressInfo addressInfo = JsonUtils.transToClass(memberFeignService.receiveAddressInfo(order.getReceiverAddressId()), MemberAddressInfo.class);
        queryPrice.setDestPostCode(addressInfo.getPostCode());
        return JsonUtils.transToClass(thirdFeignService.freightQuery(queryPrice), FreightPriceResp.class);
    }

    @Override
    public void cancelFreight(String orderSn) {
        thirdFeignService.cancelFreight(orderSn);
    }

    @Override
    @PreventRepeatSubmit(key = "#orderSn", openSpEL = true)
    public void freightSignComplete(String orderSn) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_CONFIRM_RECEIVE.getCode()).execute(orderSn);

    }

    @Override
    @PreventRepeatSubmit(key = "#orderSn", openSpEL = true)
    public void confirmSendGood(String orderSn) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_CONFIRM_SHIPMENT.getCode()).execute(orderSn);
    }

    @Override
    @PreventRepeatSubmit(key = "#orderSn", openSpEL = true)
    public void confirmGetGood(String orderSn) {
        orderFactory.getOrderUpdater(OrderEnum.ORDER_UPDATER_CONFIRM_RECEIVE.getCode()).execute(orderSn);
    }
}
